package com.zch.rpc.register.register;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 模拟注册中心客户端，供服务消费端和服务端使用
 *
 */
public class ZkClient {
	private String host;
	private Integer port;
	private Socket socket = null;//zkServer端通信
	public boolean reconnect;//是否需要重连
	public int reconnectCount;//重连的次数
	private Executor threadPoolService;
	public ZkClient(String host, Integer port) {
		this.host = host;
		this.port = port;
		this.connection();
		threadPoolService= new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
	}

	private void connection() {
		try {
			//此处的socket连接是连接到zookeeper中心
			socket = new Socket(this.host, this.port);
			if (socket != null) {
				//System.out.println("zk connect success!");
			}
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} 
	}
	
	public void close() {
		if (socket != null) {
			try {
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public void register(Message message) throws IOException {
		// 将暴露成服务的主机地址,访问端口、接口类、接口实现、注册到注册中心
		ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
		output.writeObject(message);
		// 同步阻塞等待服务器返回应答，获取应答后返回
		ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
		System.out.println("ZkClient " + input.readUTF());
		
		if (output != null) {
			output.close();
		}
		
		if (input != null) {
			input.close();
		}
	}
	
	public Message subscribe(String serviceName) throws Exception {
		ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
		Message msg = new Message();
		msg.setType("subscribe");
		msg.setInterfaceName(serviceName);
		output.writeObject(msg);
		
		// 同步阻塞等待服务器返回应答，获取应答后返回
		ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
		
		//TODO 强转前类型判断
		Message message = (Message) input.readObject();
		
		if (output != null) {
			output.close();
		}
		
		if (input != null) {
			input.close();
		}
		
		return message;
	}
    public boolean keepAlive(){
		try{
			System.out.println("准备发送心跳");
			ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
			Message msg=new Message();
			msg.setType("heart");
			output.writeObject(msg);
			// 同步阻塞等待服务器返回应答，获取应答后返回
			ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
			System.out.println("发送心跳成功并成功收到回复：" + input.readUTF());

			if (output != null) {
				output.close();
			}

			if (input != null) {
				input.close();
			}
			reconnect=false;
			return true;
		}catch (Exception e){
			e.printStackTrace();
			reconnect=true;
			return false;
		}


	}

	/*public void reconnect(Map<String, Object> services){
		threadPoolService.execute(new Runnable() {
			@Override
			public void run() {
				while(true){
					if(reconnect){//需要重连
						if(reconnectCount<=3){
							try {
								 services.forEach((k,v)->{
								 	reg
								 });
							} catch (IOException e) {
								e.printStackTrace();
							}
						}else{
							System.out.println("已重连三次,请检查服务端是否正常启动");
						}
					}
				}
			}
		});
	}*/

	public String getHost() {
		return host;
	}

	public void setHost(String host) {
		this.host = host;
	}

	public Integer getPort() {
		return port;
	}

	public void setPort(Integer port) {
		this.port = port;
	}

	public Socket getSocket() {
		return socket;
	}

	public void setSocket(Socket socket) {
		this.socket = socket;
	}
}
